package com.sinodata.bsm.cicp.collector.sqlserver;

import java.sql.ResultSet;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.collector.AbstractJDBCCollector;
import com.sinodata.bsm.cicp.exception.CollectorException;
import com.sinodata.bsm.common.constants.SeparatorConstants;
import com.sinodata.bsm.common.vo.ResPropertyValue;

public class Session extends AbstractJDBCCollector {
    private static final Logger logger = Logger.getLogger(Session.class);

    @Override
    public List<ResPropertyValue> collect(String ip) throws CollectorException {
        List<ResPropertyValue> values = new ArrayList<ResPropertyValue>();
        try {
            String[] propMetas = getPropMeta();
            String serverName = this.getParamMap().get("ServerName");
            String sql = "SELECT spid, status, hostname, program_name, memusage, cpu, physical_io, blocked,DB_NAME(dbid) db_name, cmd FROM master.dbo.sysprocesses where spid > 50";
            String[] rs = this.getStrings(serverName, sql, ip);
            ResPropertyValue propertyValueX = new ResPropertyValue();
            ResPropertyValue.PropValue[] propValues = new ResPropertyValue.PropValue[propMetas.length];
            for (int i = 0; i < propMetas.length; i++) {
                propValues[i] = ResPropertyValue.createPropValue(rs[i], propMetas[i]);
            }

            propertyValueX.setValues(propValues);
            values.add(propertyValueX);
        } catch (Exception ex) {
            logger.error("failed to collect sqlserver session", ex);
            throw new CollectorException(ex);
        }
        return values;
    }

    private String[] getStrings(String serverName, String sql, String ip) throws CollectorException {
        String[] propValArr = new String[6];

        try {
            ResultSet rst = this.getCachedResultSet("sqlserver", ip, serverName, sql);
            StringBuffer sessionDetail = new StringBuffer();
            int userSessionNum = 0;
            int activeSessionNum = 0;
            int blockedSessionNum = 0;
            int clientComputerNum = 0;
            float activePercent = 0.00F;
            Map<String, Integer> clientComputer = new HashMap<String, Integer>();
            // 进程号,状态,主机名称,程序名称,内存使用,CPU时间,物理I/O,阻塞进程ID,数据库名称,执行的命令;
            if (rst != null) {
                while (rst.next()) {
                    int spid = rst.getInt(1);
                    String hostname = rst.getString(3);
                    if (hostname != null) {
                        hostname = hostname.trim().toLowerCase();
                    }
                    if (spid > 50) {// SQL Server2000&2005
                        userSessionNum++;
                        // active session
                        String status = rst.getString(2).trim();
                        if (status != null && status.trim().equals("runnable"))
                            activeSessionNum++;
                        // blocked session
                        int blocked = rst.getInt(8);
                        if (blocked != 0)
                            blockedSessionNum++;
                        // client computer
                        if (clientComputer.get(hostname) != null) {
                            int num = Integer.parseInt(clientComputer.get(hostname).toString());
                            num++;
                            clientComputer.put(hostname, Integer.valueOf(num++));
                        } else {
                            clientComputer.put(hostname, Integer.valueOf(0));
                        }
                        String line = getTabLineStr(rst, 10);
                        sessionDetail.append(line).append(SeparatorConstants.LIN_SEPARATOR);
                    }
                }
                clientComputerNum = clientComputer.size();
                activePercent = formatDecimal(activeSessionNum * 1.0F / userSessionNum * 100);
                String sessionDetailstr = sessionDetail.toString();

                propValArr[0] = "" + userSessionNum;
                propValArr[1] = "" + activeSessionNum;
                propValArr[2] = "" + blockedSessionNum;
                propValArr[3] = "" + clientComputerNum;
                propValArr[4] = "" + activePercent;
                propValArr[5] = sessionDetailstr;
            } else {
                return null;
            }
        } catch (Exception ex) {
            logger.error("while connect database : ", ex);
            throw new CollectorException(ex);
        }
        return propValArr;
    }

    @Override
    public String[] getParamMeta() {
        return new String[] { "ServerName" };
    }

    @Override
    public String[] getPropMeta() {
        return new String[] { "UserSessions", "ActiveSessions", "BlockedSessions", "ClientComputers", "ActiveSessionPercent", "SessionDetailedInfo" };
    }

    private String getTabLineStr(ResultSet rst, int colNum) throws CollectorException {
        StringBuffer tabLineStr = new StringBuffer();
        try {
            for (int i = 1; i <= colNum; i++) {
                String val = rst.getString(i);
                if (val == null || val.trim().length() == 0) {
                    val = " ";
                } else
                    val = val.trim();
                tabLineStr.append(val).append(SeparatorConstants.COL_SEPARATOR);
            }
        } catch (Exception e) {
            logger.error("failed to get TabLineStr", e);
            throw new CollectorException(e);
        }
        return tabLineStr.toString();
    }

    private float formatDecimal(float num) {
        DecimalFormat fmt = new DecimalFormat("#.00");
        try {
            num = Float.parseFloat(fmt.format(num));
        } catch (NumberFormatException e) {
            return 0.0F;
        }
        return num;
    }

}
